<?php
/**
 * Created by PhpStorm.
 * Script Name: Mptemplatemsg.php
 * Create: 2023/1/11 9:17
 * Description:
 * Author: fudaoji<fdj@kuryun.cn>
 */

namespace plugin\wechat\app\tenant\controller;

use app\common\service\Queue;
use plugin\wechat\app\service\Mp as MpService;
use plugin\wechat\app\service\MpTemplateMsg as TemplateMsgService;
use plugin\wechat\app\service\MpFollow as FollowService;
use plugin\wechat\app\model\MpTemplatemsg as TemplateMsgM;
use plugin\wechat\app\model\MpTemplatemsgTask;
use Support\Request;

class Mptemplatemsg extends MpBase
{

    /**
     * @var TemplateMsgM
     */
    protected $model;
    /**
     * @var MpTemplatemsgTask
     */
    protected $taskM;

    public function __construct()
    {
        parent::__construct();
        $this->model = new TemplateMsgM();
        $this->taskM = new MpTemplatemsgTask();
    }

    private function tabList(){
        return [
            'task' => ['title' => '任务列表', 'href' => url('task')],
            'index' => ['title' => '消息列表', 'href' => url('index')],
            'templates' => ['title' => '模板列表', 'href' => url('templates')]
        ];
    }

    /**
     * 编辑消息
     * @param Request $request
     * @return mixed|\support\Response
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * Author: fudaoji<fdj@kuryun.cn>
     */
    public function edit(Request $request){
        $mp_info = $request->mpInfo;
        if(request()->isPost()){
            $post_data = input('post.');
            try {
                $res = $this->validate($post_data,'\\plugin\\wechat\\app\\validate\\MpTemplatemsg');
            }catch (\Exception $e){
                return $this->error($e->getMessage(), '', ['token' => token()]);
            }

            $content = [];
            foreach ($post_data as $k => $p){
                if(strpos($k, '{{') === 0){
                    $content[str_replace(['{{', "_DATA", '}}'], ['','',''], $k)] = [
                        'value' => $p,
                        'color' => $post_data['color_'.$k]
                    ];
                }
            }
            $data = [
                'id' => $post_data['id'],
                'title' => $post_data['title'],
                'url' => $post_data['url'],
                'speed' => $post_data['speed'],
                'content' => json_encode($content, JSON_UNESCAPED_UNICODE),
                'preview' => $post_data['preview'] ?: ''
            ];

            return parent::savePost($request, '', $data);
        }
        $id = input('id');
        $data = $this->model->where([
            $this->tenantWhere(),
            ['mp_id', '=', $mp_info['id']]
        ])->find($id);
        if(empty($data)){
            return $this->error('数据不存在');
        }
        if(is_string($res = MpService::templateMessagePull())){
            return $this->error($res, '', ['token' => token()]);
        }
        if(empty($res['template_list'])){
            return $this->error('请先到公众号后台开启模版消息！', '', ['token' => token()]);
        }
        $template_list = $res['template_list'];
        $template = [];
        foreach ($template_list as $item){
            if($item['template_id'] == $data['template_id']){
                $template = $item;
                break;
            }
        }
        if(empty($template)){
            return $this->error('此消息对应的模版不存在或已被禁用！', '');
        }
        preg_match_all("/(\{\{.*\}\})/", $template['content'], $keywords);
        $keywords = $keywords[0];
        $content = json_decode($data['content'], true);
        foreach ($keywords as $k => $v){
            $r = str_replace(['{{', ".DATA", '}}'], ['','',''], $v);
            if(isset($content[$r])){
                $content[$r]['key'] = $v;
                $template['content'] = str_replace($v, '<span style="color:'.$content[$r]['color'].'">'.$content[$r]['value'].'</span>', $template['content']);
            }
        }

        $builder = new FormBuilder();
        $builder->setTemplate('mptemplatemsg/edit')
            ->addFormItem('id', 'hidden', 'id', 'id')
            ->addFormItem('title', 'text', '标题', '消息标题，50字符内', [], 'required maxlength=50')
            ->addFormItem('url', 'text', '跳转链接', '跳转链接', [], ' maxlength=200')
            ->addFormItem('speed', 'number', '推送速度', '每秒推送条数，根据服务器带宽设置，每5M可增大10.例如5M->10,10M->20', [], ' min=1 max=300')
            ->setFormData($data);
        $assign = [
            'template' => $template,
            'keywords' => $content,
        ];
        return $builder->show($assign);
    }

    /**
     * 创建消息
     * @param Request $request
     * @return mixed|\support\Response
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     * Author: fudaoji<fdj@kuryun.cn>
     */
    public function add(Request $request){
        $mp_info = $request->mpInfo;
        if(request()->isPost()){
            $post_data = input('post.');
            try {
                $res = $this->validate($post_data,'\\plugin\\wechat\\app\\validate\\MpTemplatemsg');
            }catch (\Exception $e){
                return  $this->error($e->getMessage(), '', ['token' => token()]);
            }

            $content = [];
            foreach ($post_data as $k => $p){
                if(strpos($k, '{{') === 0){
                    $content[str_replace(['{{', "_DATA", '}}'], ['','',''], $k)] = [
                        'value' => $p,
                        'color' => $post_data['color_'.$k]
                    ];
                }
            }
            $data = [
                'mp_id' => $mp_info['id'],
                'template_id' => $post_data['template_id'],
                'title' => $post_data['title'],
                'url' => $post_data['url'],
                'speed' => $post_data['speed'],
                'content' => json_encode($content, JSON_UNESCAPED_UNICODE),
                'preview' => $post_data['preview'] ?: ''
            ];
            return parent::savePost($request, url('index'), $data);
        }
        if(is_string($res = MpService::templateMessagePull())){
            return $this->error($res, '', ['token' => token()]);
        }
        if(empty($res['template_list'])){
            return $this->error('请先到公众号后台开启模版消息！', '', ['token' => token()]);
        }
        $template_list = $res['template_list'];
        $template = [];
        foreach ($template_list as $item){
            if($item['template_id'] == input('template_id')){
                $template = $item;
                break;
            }
        }
        if(empty($template)){
            return $this->error('参数错误');
        }
        preg_match_all("/(\{\{.*\}\})/", $template['content'], $keywords);

        $builder = new FormBuilder();
        $builder->setTemplate('mptemplatemsg/add')
            ->addFormItem('template_id', 'hidden', 'template_id', 'template_id')
            ->addFormItem('title', 'text', '标题', '消息标题，50字符内', [], 'required maxlength=50')
            ->addFormItem('url', 'text', '跳转链接', '跳转链接', [], ' maxlength=200')
            ->addFormItem('speed', 'number', '推送速度', '每秒推送条数，根据服务器带宽设置，每5M可增大10.例如5M->10,10M->20', [], ' min=1 max=300')
            ->setFormData($template);
        $assign = [
            'template' => $template,
            'keywords' => $keywords[0]
        ];
        return $builder->show($assign);
    }

    /**
     * 消息列表
     * @param Request $request
     * @return mixed|\support\Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function index(Request $request)
    {
        $mp_info = $request->mpInfo;
        if (request()->isPost()) {
            $post_data = input('post.');
            $where = [
                $this->tenantWhere(),
                ['mp_id', '=', $mp_info['id']]
            ];
            !empty($post_data['search_key']) && $where[] = [
                'title', 'like', '%' . $post_data['search_key'] . '%'
            ];
            $query = $this->model->where($where);
            $total = $query->count();
            if ($total) {
                $list = $query->page($post_data['page'], $post_data['limit'])
                    ->order('id', 'desc')
                    ->select();
            } else {
                $list = [];
            }
            return $this->success('success', '', ['total' => $total, 'list' => $list]);
        }

        $builder = new ListBuilder();
        $builder->setTabNav($this->tabList(), __FUNCTION__)
            ->setSearch([
                ['type' => 'text', 'name' => 'search_key', 'title' => '关键词', 'placeholder' => '消息名称']
            ])
            ->addTableColumn(['title' => '消息名称', 'field' => 'title', 'minWidth' => 100])
            ->addTableColumn(['title' => '模版ID', 'field' => 'template_id',  'minWidth' => 120])
            ->addTableColumn(['title' => '内容', 'field' => 'preview', 'type' => 'pre','minWidth' => 250])
            ->addTableColumn(['title' => '跳转链接', 'field' => 'url', 'minWidth' => 150])
            ->addTableColumn(['title' => '推送速度/秒', 'field' => 'speed', 'minWidth' => 90])
            ->addTableColumn(['title' => '创建时间', 'field' => 'create_time', 'minWidth' => 170])
            ->addTableColumn(['title' => '操作', 'minWidth' => 120, 'type' => 'toolbar'])
            ->addRightButton('edit')
            ->addRightButton('edit', ['text' => '发送预览','class' => 'layui-btn-default', 'href' => url('previewMsg', ['id' => '__data_id__'])]);
        return $builder->show();
    }

    /**
     * 模版列表
     * @param Request $request
     * @return mixed|\support\Response
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     * Author: fudaoji<fdj@kuryun.cn>
     */
    public function templates(Request $request)
    {
        $mp_info = $request->mpInfo;
        if($mp_info['verify_type_info'] < 0){
            return $this->error('当前公众号未获得模板消息权限');
        }
        if (request()->isPost()) {
            $post_data = input('post.');
            if(is_string($res = MpService::templateMessagePull())){
                return $this->error($res, '', ['token' => token()]);
            }
            $list = $res['template_list'] ?? [];
            $total = count($list);
            return $this->success('success', '', ['total' => $total, 'list' => $list]);
        }

        $builder = new ListBuilder();
        $builder->setTabNav($this->tabList(), __FUNCTION__)
            ->addTableColumn(['title' => '模版ID', 'field' => 'template_id',  'minWidth' => 150])
            ->addTableColumn(['title' => '模版名称', 'field' => 'title', 'minWidth' => 100])
            ->addTableColumn(['title' => '主行业', 'field' => 'primary_industry', 'minWidth' => 100])
            ->addTableColumn(['title' => '副行业', 'field' => 'deputy_industry', 'minWidth' => 100])
            ->addTableColumn(['title' => '模版内容', 'field' => 'content', 'type' => 'pre','minWidth' => 200])
            ->addTableColumn(['title' => '样例', 'field' => 'example', 'type' => 'pre', 'minWidth' => 200])
            ->addTableColumn(['title' => '操作', 'minWidth' => 90, 'type' => 'toolbar'])
            ->addRightButton('edit', ['href' => url('add', ['template_id' => '__data_template_id__']),'title' => '创建消息', 'text' => '创建消息']);

        return $builder->show();
    }

    /**
     * 任务列表
     * @param Request $request
     * @return mixed|\support\Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * Author: fudaoji<fdj@kuryun.cn>
     */
    public function task(Request $request)
    {
        $mp_info = $request->mpInfo;
        if (request()->isPost()) {
            $post_data = input('post.');
            $where = [
                $this->tenantWhere('task'),
                ['task.mp_id', '=', $mp_info['id']]
            ];
            !empty($post_data['search_key']) && $where[] = [
                'msg.title', 'like', '%' . $post_data['search_key'] . '%'
            ];
            $query = $this->taskM->alias('task')
                ->join($request->plugin . '_mp_templatemsg msg', 'task.templatemsg_id=msg.id')
                ->where($where);
            $total = $query->count();
            if ($total) {
                $list = $query->page($post_data['page'], $post_data['limit'])
                    ->field(['task.*', 'msg.title as msg_title'])
                    ->order('task.id', 'desc')
                    ->select();
                foreach ($list as $k => $v){
                    $v['count'] = $v['count'] . '/' . $v['total'];
                    $v['complete_time'] = $v['complete_time'] ? date('Y-m-d H:i', $v['complete_time']) : '- - -';
                    $v['push_time'] = date('Y-m-d H:i', $v['push_time']);
                    $v['status_title'] = TemplateMsgService::statusList($v['status']);
                    $list[$k] = $v;
                }
            } else {
                $list = [];
            }
            return $this->success('success', '', ['total' => $total, 'list' => $list]);
        }

        $builder = new ListBuilder();
        $builder->setTabNav($this->tabList(), __FUNCTION__)
            ->setSearch([
                ['type' => 'text', 'name' => 'search_key', 'title' => '关键词', 'placeholder' => '消息名称']
            ])
            ->addTopButton('addnew', ['href' => url('taskAdd')])
            ->addTableColumn(['title' => '任务ID', 'field' => 'id', 'minWidth' => 80])
            ->addTableColumn(['title' => '任务名称', 'field' => 'title',  'minWidth' => 150])
            ->addTableColumn(['title' => '消息名称', 'field' => 'msg_title', 'type' => 'pre','minWidth' => 200])
            ->addTableColumn(['title' => '推送时间', 'field' => 'push_time', 'minWidth' => 180])
            ->addTableColumn(['title' => '已完成/应完成', 'field' => 'count', 'type' => 'pre','minWidth' => 200])
            ->addTableColumn(['title' => '状态', 'field' => 'status_title', 'minWidth' => 200])
            ->addTableColumn(['title' => '创建时间', 'field' => 'create_time', 'minWidth' => 180])
            ->addTableColumn(['title' => '完成时间', 'field' => 'complete_time', 'minWidth' => 180])
            ->addTableColumn(['title' => '操作', 'minWidth' => 130, 'type' => 'toolbar'])
            ->addRightButton('delete', ['class' => 'layui-btn-warm','text' => '停止|继续', 'href' => url('taskStopPost', ['id' => '__data_id__'])])
            ->addRightButton('edit', ['href' => url('taskEdit', ['id' => '__data_id__'])]);

        return $builder->show();
    }

    /**
     * 新增任务
     * @param Request $request
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * Author: fudaoji<fdj@kuryun.cn>
     */
    public function taskAdd(Request $request){
        $mp_info = $request->mpInfo;
        $msg_list = $this->model->where([
            $this->tenantWhere(),
            ['status' ,'=', 1],
            ['mp_id','=', $mp_info['id']]
        ])
        ->order(['id' => 'desc'])
        ->column('title', 'id');
        $builder = new FormBuilder();
        $builder->setPostUrl(url('tasksavepost'))
            ->addFormItem('templatemsg_id', 'select', '选择消息', '选择消息', $msg_list, 'required')
            ->addFormItem('title', 'text', '任务名称', '50字符内', [], 'required maxlength=50')
            ->addFormItem('push_time', 'datetime', '推送时间', '不填则立即推送');
        return $builder->show();
    }

    /**
     * 编辑任务
     * @param Request $request
     * @return mixed|\support\Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * Author: fudaoji<fdj@kuryun.cn>
     */
    public function taskEdit(Request $request){
        $mp_info = $request->mpInfo;
        if(! $data = $this->taskM->where([$this->tenantWhere()])->find(input('id'))){
            return $this->error('数据不存在');
        }
        if(! in_array($data['status'], [0])){
            return $this->error('此任务禁止修改');
        }
        $msg_list = $this->model->where([
            $this->tenantWhere(),
            ['status' ,'=', 1],
            ['mp_id','=', $mp_info['id']]
        ])
            ->order(['id' => 'desc'])
            ->column('title', 'id');
        $builder = new FormBuilder();
        $builder->setTip("只有在任务未开始前才能修改")
            ->setPostUrl(url('tasksavepost'))
            ->addFormItem('id', 'hidden', 'id', 'id')
            ->addFormItem('templatemsg_id', 'select', '选择消息', '选择消息', $msg_list, 'required')
            ->addFormItem('title', 'text', '任务名称', '50字符内', [], 'required maxlength=50')
            ->addFormItem('push_time', 'datetime', '推送时间', '不填则立即推送')
            ->setFormData($data);
        return $builder->show();
    }

    /**
     * 任务保存
     * @param Request $request
     * @return \support\Response
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \think\db\exception\DbException
     * @throws \Psr\SimpleCache\InvalidArgumentException
     * Author: fudaoji<fdj@kuryun.cn>
     */
    public function taskSavePost(Request $request){
        $mp_info = $request->mpInfo;
        if(request()->isPost()){
            $post_data = input('post.');
            $res = $this->validate($post_data,'\\plugin\\wechat\\app\\validate\\MpTemplatemsgTask');

            if($res !== true){
                return $this->error($res, '', ['token' => token()]);
            }
            $post_data['company_id'] = $mp_info['company_id'];
            $post_data['mp_id'] = $mp_info['id'];
            if(empty($post_data['push_time'])){
                $post_data['push_time'] = time();
            }else{
                $post_data['push_time'] = strtotime($post_data['push_time']);
            }
            $wx_res = FollowService::userList();
            if(!empty($wx_res['total'])){
                $post_data['total'] = $wx_res['total'];
            }
            if(empty($post_data['id'])){
                $res = $this->taskM->createOne($post_data);
            }else{
                $res = $this->taskM->update($post_data);
            }
            if($res){
                Queue::push([
                    'consumer' => ['\\plugin\\wechat\\app\\queue\\TemplateMsg', 'pushTask'],
                    'task_id' => $res['id'],
                    'delay' => max(1, $res['push_time'] - time())
                ]);
                return $this->success('保存成功', '');
            }else{
                return $this->error('保存失败，请刷新重试', '', ['token' => token()]);
            }
        }
    }

    /**
     * 停止任务
     * @return \support\Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * Author: fudaoji<fdj@kuryun.cn>
     */
    public function taskStopPost()
    {
        if (request()->isPost()) {
            $post_data = input('post.');
            $task = $this->taskM->where([$this->tenantWhere()])->find($post_data['ids']);
            if(! $task){
                return $this->error('此任务不存在', '', ['token' => token()]);
            }
            $this->taskM->update([
                'id' => $task['id'],
                'status' => $task['status'] == 3 ? 1 : 3
            ]);
            if($task['status'] == 3){
                Queue::push([
                    'consumer' => ['\\plugin\\wechat\\app\\queue\\TemplateMsg', 'pushTask'],
                    'task_id' => $task['id'],
                    'delay' => max(1, $task['push_time'] - time())
                ]);
            }
            return $this->success('操作成功！', '');
        }
    }

    /**
     * 模板消息预览
     * @param Request $request
     * @return mixed|\support\Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * Author: fudaoji<fdj@kuryun.cn>
     */
    public function previewMsg(Request $request){
        $id = $request->input('id');
        $data = $this->model->where([
            $this->tenantWhere(),
            ['mp_id', '=', $request->mpInfo['id']]
        ])->find($id);
        if(empty($data)){
            return $this->error('数据不存在', '', ['token' => token()]);
        }
        if($request->isPost()){
            $post_data = input('post.');
            $openids = explode(',', $post_data['openid']);
            try {
                foreach ($openids as $k => $openid){
                    //发消息
                    Queue::push([
                        'consumer' => ['\\plugin\\wechat\\app\\queue\\TemplateMsg', 'send'],
                        'task' => $data,
                        'mp_info' => $request->mpInfo,
                        'to' => $openid,
                        'client_msg_id' => $k . time()
                    ]);
                }
                return  $this->success('发送成功!');
            }catch (\Exception $e){
                return $this->error('发送错误:' . $e->getMessage(), '', ['token' => token()]);
            }
        }

        $builder = new FormBuilder();
        $builder->setPostUrl(url('previewMsg'))
            ->setTip("点击查看如何获取预览者openid？")
            ->addFormItem('id', 'hidden', 'id', 'id')
            ->addFormItem('msg', 'static', '模板消息', $data['title'])
            ->addFormItem('openid', 'text', '预览者openid', '多个openid用英文,分割', [], 'required')
            ->setFormData($data);
        return $builder->show();
    }
}